10. Service Locators
L5 P3 A06 Service Locators
Let's make a ServiceLocator class
Step 1: Create the ServiceLocator
- Create the file ServiceLocator.kt in the top level of the main source set.
- Define an object called
ServiceLocator. - Create database and repository instance variables and set both to null.
- Annotate the repository with @Volatile because it could get used by multiple threads (
@Volatileis explained in detail here).
Your code should look like this:
ServiceLocator.kt
object ServiceLocator {
private var database: ToDoDatabase? = null
@Volatile
var tasksRepository: TasksRepository? = null
}
Right now the only thing your ServiceLocator needs to do is know how to return a TasksRepository. It'll return a pre-existing DefaultTasksRepository or make and return a new DefaultTasksRepository if needed.
You'll define the following functions:
provideTasksRepository- Either provides an already existing repository or creates a new one. This method should be synchronized onthisto avoid, in situations with multiple threads running, ever accidentally creating two repository instances.createTasksRepository- Code for creating a new repository. Will callcreateTaskLocalDataSourceand create a newTasksRemoteDataSource.createTaskLocalDataSource- Code for creating a new local data source. Will callcreateDataBase.createDataBase- Code for creating a new database.
The completed code is below:
ServiceLocator.kt
object ServiceLocator {
private var database: ToDoDatabase? = null
@Volatile
var tasksRepository: TasksRepository? = null
fun provideTasksRepository(context: Context): TasksRepository {
synchronized(this) {
return tasksRepository ?: createTasksRepository(context)
}
}
private fun createTasksRepository(context: Context): TasksRepository {
val newRepo = DefaultTasksRepository(TasksRemoteDataSource, createTaskLocalDataSource(context))
tasksRepository = newRepo
return newRepo
}
private fun createTaskLocalDataSource(context: Context): TasksDataSource {
val database = database ?: createDataBase(context)
return TasksLocalDataSource(database.taskDao())
}
private fun createDataBase(context: Context): ToDoDatabase {
val result = Room.databaseBuilder(
context.applicationContext,
ToDoDatabase::class.java, "Tasks.db"
).build()
database = result
return result
}
}
Good job. Now that you have a ServiceLocator, you'll use it next.